package com.atguigu.spzx.product.service.impl;

import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.product.mapper.CategoryMapper;
import com.atguigu.spzx.product.service.CategoryService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
//    @Resource  存储简单类型数据 使用   复杂类型数据需要手动转为json字符串存储 读取时需要手动还原
//    StringRedisTemplate stringRedisTemplate;
    //redisTemplate 默认以二进制序列化的形式保存对象  再图形化工具中他存储的数据不可读  自定义类型必须实现序列化接口
    //RedisTemplate 可以设置键和值的序列化器 自动将对象转为json字符串写入缓存，自动将读取到的缓存json字符串还原为java对象
    @Resource
    RedisTemplate redisTemplate;
//    @CacheEvict
//    @CachePut
    //unless="result.size()==0"  如果返回的集合长度为0  不缓存
    @Cacheable(value = "spzx:cache:cates"  , key = "'all'")//value+key组成了缓存的键， value写固定内容，key可以使用表达式
    //spzx:cates::all
    @Override
    public List<Category> findCategoryTree() {
        List<Category> categories = baseMapper.selectList(Wrappers.lambdaQuery(Category.class)
                .eq(Category::getDeleted, 0));
        //组装为父子关系
        //1、挑选一级分类列表
        List<Category> parents = categories.stream().filter(category -> category.getParentId().equals(0L)).collect(Collectors.toList());
        buildCategoryTree(parents , categories);
        return parents;
    }
    //使用RedisTemplate缓存管理
//    @Override
//    public List<Category> findCategoryTree() {
//        //1、先查询缓存是否有数据，有直接返回
//        Object obj = redisTemplate.opsForValue().get("spzx:cates:all");
//        if(obj!=null){
//            return (List<Category>) obj;
//        }
//        //2、没有命中缓存，走数据库查询
//        List<Category> categories = baseMapper.selectList(Wrappers.lambdaQuery(Category.class)
//                .eq(Category::getDeleted, 0));
//        //组装为父子关系
//        //1、挑选一级分类列表
//        List<Category> parents = categories.stream().filter(category -> category.getParentId().equals(0L)).collect(Collectors.toList());
//        buildCategoryTree(parents , categories);
//        //3、将查询到的结果缓存到redis
//        redisTemplate.opsForValue().set("spzx:cates:all",parents ,600 , TimeUnit.SECONDS);
//        return parents;
//    }
    private void buildCategoryTree(List<Category> parents, List<Category> categories) {
        if(CollectionUtils.isEmpty(parents)){
            return;
        }
        //遍历所有的父分类
        parents.forEach(parent -> {
            //获取正在遍历的父分类的 下一级分类集合
            List<Category> children = categories.stream()
                    .filter(category -> category.getParentId().equals(parent.getId())).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(children)){
                parent.setChildren(children);
                //再给children查找下一级设置
                buildCategoryTree(children , categories);
            }
        });

    }
}
